// Package captcha 处理图片验证码逻辑，支持: 1. 生成图片验证码 2. 校验图片验证码
// 支持的存储：redis, memory
package captcha

import (
	"sync"

	"github.com/mojocn/base64Captcha"
	"github.com/runningwater/gohub/pkg/app"
	"github.com/runningwater/gohub/pkg/config"
	"github.com/runningwater/gohub/pkg/redis"
)

type Captcha struct {
	base64Captcha *base64Captcha.Captcha
}

// 确保 internalCaptcha 只初始化一次
// 通过 sync.Once 确保线程安全
var one sync.Once

var internalCaptcha *Captcha

// NewCaptcha 创建一个新的验证码实例
func NewCaptcha() *Captcha {
	one.Do(func() {
		// 初始化 Captcha 实例
		internalCaptcha = &Captcha{}

		// 使用 redis 作为存储引擎，并设置 key 的前缀
		store := RedisStore{
			RedisClient: redis.Redis,
			KeyPrefix:   config.GetString("app.name") + ":captcha:",
		}

		// 配置 base64Captcha 驱动信息
		driver := base64Captcha.NewDriverDigit(
			config.GetInt("captcha.height"),      // 高度
			config.GetInt("captcha.width"),       // 宽度
			config.GetInt("captcha.length"),      // 长度
			config.GetFloat64("captcha.maxskew"), // 最大倾斜角度
			config.GetInt("captcha.dotcount"),    // 图片背景里的混淆点数量
		)

		// 创建 base64Captcha 实例
		internalCaptcha.base64Captcha = base64Captcha.NewCaptcha(driver, &store)
	})

	return internalCaptcha
}

// GenerateCaptcha 生成验证码
func (c *Captcha) GenerateCaptcha() (id, b64s, answer string, err error) {
	return c.base64Captcha.Generate()
}

// VerifyCaptcha 校验验证码
func (c *Captcha) VerifyCaptcha(id, answer string) (match bool) {
	// 方便本地开发调试
	if !app.IsProduction() && id == config.GetString("captcha.testing_key") {
		return true
	}
	// 第三个参数是验证后是否删除，我们选择 false
	// 这样方便用户多次提交，防止表单提交错误需要多次输入图片验证码
	return c.base64Captcha.Verify(id, answer, false)
}
